1 Introduction

For this project, I am continuing with my Airplane Crash Data Since 1908 dataset. I am really excited to begin this project as I know I will be able to accomplish the analysis that I did not get to explore last time. That being said, I plan to explore the Operator data to see the operators with the most crashes, the Summary data to see what were the top crash explanations, and the Long and Lat data to see exactly where these crashes occurred.

1.1 The Dataset

crashes <- read.csv("../data/airplanesData.csv")
head(crashes)

2 Data Wrangling and Exploration

summary(crashes)
     ï..ID          Date               Time             Location        
 Min.   :   1   Length:4967        Length:4967        Length:4967       
 1st Qu.:1242   Class :character   Class :character   Class :character  
 Median :2484   Mode  :character   Mode  :character   Mode  :character  
 Mean   :2484                                                           
 3rd Qu.:3726                                                           
 Max.   :4967                                                           
                                                                        
      Lat                Long           Operator           Flight..        
 Min.   :     -16   Min.   :-176.66   Length:4967        Length:4967       
 1st Qu.:      19   1st Qu.: -98.61   Class :character   Class :character  
 Median :      35   Median : -85.00   Mode  :character   Mode  :character  
 Mean   :   10222   Mean   : -76.64                                        
 3rd Qu.:      41   3rd Qu.: -73.70                                        
 Max.   :50626552   Max.   : 174.12                                        
                                                                           
    Route             AC.Type          Registration          cn.ln          
 Length:4967        Length:4967        Length:4967        Length:4967       
 Class :character   Class :character   Class :character   Class :character  
 Mode  :character   Mode  :character   Mode  :character   Mode  :character  
                                                                            
                                                                            
                                                                            
                                                                            
     Aboard       Aboard.Passangers  Aboard.Crew      Fatalities    
 Min.   :  0.00   Min.   :  0.0     Min.   : 0.00   Min.   :  0.00  
 1st Qu.:  7.00   1st Qu.:  3.0     1st Qu.: 2.00   1st Qu.:  4.00  
 Median : 16.00   Median : 12.0     Median : 4.00   Median : 11.00  
 Mean   : 31.09   Mean   : 26.9     Mean   : 4.48   Mean   : 22.34  
 3rd Qu.: 35.00   3rd Qu.: 30.0     3rd Qu.: 6.00   3rd Qu.: 25.00  
 Max.   :644.00   Max.   :614.0     Max.   :61.00   Max.   :583.00  
 NA's   :18       NA's   :229       NA's   :226     NA's   :8       
 Fatalities.Passangers Fatalities.Crew      Ground           Summary         
 Min.   :  0.00        Min.   : 0.000   Min.   :   0.000   Length:4967       
 1st Qu.:  1.00        1st Qu.: 2.000   1st Qu.:   0.000   Class :character  
 Median :  8.00        Median : 3.000   Median :   0.000   Mode  :character  
 Mean   : 19.02        Mean   : 3.579   Mean   :   1.728                     
 3rd Qu.: 21.00        3rd Qu.: 5.000   3rd Qu.:   0.000                     
 Max.   :560.00        Max.   :46.000   Max.   :2750.000                     
 NA's   :242           NA's   :241      NA's   :41                           
crashes <- separate(data = crashes,col = Date, into = c("Month", "Day", "Year"), sep = "\\/")
crashes <- separate(data = crashes, col = Location, into = c("City", "Region", "Country"), sep = "\\, ")
Expected 3 pieces. Additional pieces discarded in 9 rows [150, 663, 1722, 2369, 2601, 2849, 3139, 3707, 4848].Expected 3 pieces. Missing pieces filled with `NA` in 4611 rows [1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, ...].

2.1 Operator Data Analysis

The below code was used for the Crashes Per Operator Per State graph.

small_DF <- crashes %>% 
  group_by(Operator) %>% 
  count(Operator) %>% 
  arrange(desc(n)) %>% 
  filter(n > 50)
operatorData <- crashes %>%
  group_by(Operator, Year) %>% 
  count(Operator) %>% 
  arrange(desc(n)) %>% 
  filter(n > 0)

operatorData
df <- operatorData %>%
  filter(Operator %in% small_DF$Operator) %>%
  group_by(Year)

df

2.2 Crash Count Per State Data Analysis

The below code was used for the Crash Count Per State graph.

my_sf <- st_as_sf(filter(crashes, Long<0, Lat>0), coords = c('Long', 'Lat'))
state_map_data <- map('state', fill = TRUE, plot = FALSE) %>% st_as_sf()
my_sf<-st_set_crs(my_sf, st_crs(state_map_data))
sf::sf_use_s2(FALSE)
Spherical geometry (s2) switched off
state_map_data$crash_count <- lengths(st_intersects(state_map_data,my_sf))
although coordinates are longitude/latitude, st_intersects assumes that they are planar

2.3 Crashes Location Data Analysis

The below code was used for the Crash Location graph.

df_geom <- crashes %>%
  group_by(Year) %>% 
  filter(Region %in% c("Alabama", "Arizona", "Arkansas", "California", "Colardo", "Connecticut", "Delaware", "Florida", "Georgia", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucy", "Lousiana", "Maine", "Maryland", "Massachettusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", "Wyoming")) %>%
 select(Year, Region, Long, Lat)
  
my_sf2 <- st_as_sf(filter(df_geom, Long<0, Lat>24), coords = c('Long', 'Lat'))
state_map_data2 <- map('state', fill = TRUE, plot = FALSE) %>% st_as_sf()
my_sf2 <- st_set_crs(my_sf2, st_crs(state_map_data))
sf::sf_use_s2(FALSE)
state_map_data$crash_count <- lengths(st_intersects(state_map_data,my_sf2))
although coordinates are longitude/latitude, st_intersects assumes that they are planar

2.4 Bigram Data Analysis

The below code was used for the Crash Summary Bigram graph.

bigramData <- crashes %>% 
  select(Summary)

bigramData
sum_bigram <- bigramData %>% 
  unnest_tokens(bigram, Summary,
                token = "ngrams", n = 2)
sum_bigram %>% 
  count(bigram, sort = TRUE)
bigrams_filtered <- sum_bigram %>% 
  separate(bigram, into = c("word1", "word2"), sep = " ") %>% 
  filter(!word1 %in% stop_words$word) %>%
  filter(!word2 %in% stop_words$word)
bigram_count <- bigrams_filtered %>% 
  count(word1, word2, sort = TRUE)
bigram_count
bigram_unite <- bigrams_filtered %>% 
  unite(bigram, word1, word2, sep = " ")
bigram_unite
bigram_graph <- bigram_count %>% 
  filter(n > 60) %>% 
  graph_from_data_frame()

3 Data Visualizations

3.1 Crashes per Operator over Time

f <- ggplot(data = df, aes(x = Year, y = n, color = Operator, group = 1)) +
  geom_point(palette = "Blues")+
  geom_line(palette = "Blues")+
  labs(title = "Crashes Per Operator Per Year",
       y = " ",
       x = "Year")+
  theme_minimal()+
  #scale_x_continuous(expand = )+
  theme(plot.title.position = "plot")
Ignoring unknown parameters: paletteIgnoring unknown parameters: palette
ggplotly(f)

This graph shows the top 4 operators that had the most crashes. You can hover over the point to see which year it occured in, the number of crashs, and the operator. One of the things i found intresting from this graph is that Deutsche Lufthansa made it into the top 4 for most crashes, but was only had crashes from 1908-1945. Something that may be worth looking at is a crash ratio or flights flown to flights crashed.

3.2 Crash Count by State

k <- ggplot() +
  geom_sf(data = state_map_data, aes(fill = crash_count))+
  scale_fill_distiller(palette="Reds", direction = +1)+
  labs(title = "Crash Count Per State")+
  guides(fill = FALSE)+
  theme_minimal()+
  theme(plot.title.position = "plot")
`guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> = "none")` instead.
ggplotly(k)

In this graph, we can see the number of crashes that occured in each state.

3.3 Crash Location

p <- ggplot() +
  geom_sf(data = state_map_data)+
  geom_sf(data = my_sf2, color = 'red', size = 0.1)+
  theme_minimal()+
  labs(title = "Crash Location per State")+
  theme(plot.title.position = "plot")

ggplotly(p)

Building on the last graph, this one shows the location of each crash in the state.

3.4 Crash Summary Bigram

set.seed(2021)
a <- grid::arrow(
  type = "closed",
  length = unit(.12, "inches")
)

ggraph(bigram_graph, layout = "kk") +
  geom_edge_link(
    aes(edge_alpha = n),
    show.legend = FALSE, arrow = a,
    edge_width = 1) +
  geom_node_point(color = "black",
                  size = 4) +
  geom_node_text(aes(label = name), vjust = 1, hjust = 1)+
  labs(title = "Crash Summary Bigram")+
  theme_minimal()+
  theme(plot.title.position = "plot")

In this model, we can see the most common word parings from the crash summary. I thought this would be intresting to explore as it could give some insight into what caused the crash.


4 Conclusion

This analysis helped me see a different side of this data. It showed me the where and why that I missed in my first project. It was interesting to explore the different states counts, and the the individual location of each crash. It was even a little surprising to find out that California had the most crashes out of the continental US. As for the crash explanations, so were to be expected, like engine -> failure or weather -> conditions, but I thought it was interesting to see some like caught -> fire and struck -> tree.

5 Future Works

I am really disappointed that I was not able to get ‘gganimate’ to work, and I hope to implement that in my future analysis. Additionally, I had a ‘leaflet’ plot that was really messy, so I hope to refine that and add that to a future version of this project.

date_df <- select(crashes, c(Month, Year, Fatalities, Aboard, AC.Type, Long, Lat))
#Changing the data type of fatalities to a numeric
date_df$Fatalities <- as.numeric(date_df$Fatalities)
#Changing all the NAs to 0s
date_df[is.na(date_df)] <- 0
#Changing the data type of year to a numeric
date_df$Year <- as.numeric(date_df$Year)
#Creating a new column in our dataset called decade
date_df <- date_df %>% 
  mutate(Decade = floor(Year/10) * 10)
international_sf <- st_as_sf(date_df, coords = c('Long', 'Lat'))
international_sf <- st_set_crs(international_sf, st_crs(state_map_data3))
state_map_data3 <- maps::map('state', fill = TRUE, plot = FALSE) %>% 
  st_as_sf()
library(leaflet)
leaflet() %>% 
  addTiles() %>% 
  addCircleMarkers(data = international_sf, fillColor = international_sf$Year, fillOpacity = 1, stroke = FALSE, radius = 5, group = international_sf$Year) %>% 
  addLayersControl(overlayGroups = international_sf$Year, options = layersControlOptions(collapsed = FALSE))
bounding box has potentially an invalid value range for longlat data
LS0tDQp0aXRsZTogIkRhdGEgVmlzdWFsaXphdGlvbiAtIE1pbmktUHJvamVjdCAyIg0KYXV0aG9yOiAiS2FpdGx5biBTY2hlcHBhIGBrc2NoZXBwYTQ3MDdAZmxvcmlkYXBvbHkuZWR1YCINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6DQogICAgdG9jOiBUUlVFDQogICAgdG9jX2Zsb2F0OiBUUlVFDQogICAgdG9jX2RlcHRoOiA0DQogICAgbnVtYmVyX3NlY3Rpb25zOiBUUlVFDQogICAgdGhlbWU6IHVuaXRlZA0KLS0tDQoNCmBgYHtyLCBlY2hvID0gRkFMU0UsIHJlc3VsdHM9J2hpZGUnfQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGlkeXRleHQpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkodGlkeXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGlncmFwaCkNCmxpYnJhcnkoZ2dyYXBoKQ0KbGlicmFyeShzY2FsZXMpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KG1hcHZpZXcpDQpsaWJyYXJ5KG1hcHMpDQpsaWJyYXJ5KGdnbWFwKQ0KbGlicmFyeShzZikNCmBgYA0KDQoNCiMgSW50cm9kdWN0aW9uDQoNCkZvciB0aGlzIHByb2plY3QsIEkgYW0gY29udGludWluZyB3aXRoIG15IGBBaXJwbGFuZSBDcmFzaCBEYXRhIFNpbmNlIDE5MDhgIGRhdGFzZXQuIEkgYW0gcmVhbGx5IGV4Y2l0ZWQgdG8gYmVnaW4gdGhpcyBwcm9qZWN0IGFzIEkga25vdyBJIHdpbGwgYmUgYWJsZSB0byBhY2NvbXBsaXNoIHRoZSBhbmFseXNpcyB0aGF0IEkgZGlkIG5vdCBnZXQgdG8gZXhwbG9yZSBsYXN0IHRpbWUuIFRoYXQgYmVpbmcgc2FpZCwgSSBwbGFuIHRvIGV4cGxvcmUgdGhlIGBPcGVyYXRvcmAgZGF0YSB0byBzZWUgdGhlIG9wZXJhdG9ycyB3aXRoIHRoZSBtb3N0IGNyYXNoZXMsIHRoZSBgU3VtbWFyeWAgZGF0YSB0byBzZWUgd2hhdCB3ZXJlIHRoZSB0b3AgY3Jhc2ggZXhwbGFuYXRpb25zLCBhbmQgdGhlIGBMb25nYCBhbmQgYExhdGAgZGF0YSB0byBzZWUgZXhhY3RseSB3aGVyZSB0aGVzZSBjcmFzaGVzIG9jY3VycmVkLg0KDQoNCiMjIFRoZSBEYXRhc2V0DQpgYGB7cn0NCmNyYXNoZXMgPC0gcmVhZC5jc3YoIi4uL2RhdGEvYWlycGxhbmVzRGF0YS5jc3YiKQ0KaGVhZChjcmFzaGVzKQ0KYGBgDQotLS0NCg0KIyBEYXRhIFdyYW5nbGluZyBhbmQgRXhwbG9yYXRpb24NCmBgYHtyfQ0Kc3VtbWFyeShjcmFzaGVzKQ0KYGBgDQpgYGB7cn0NCmNyYXNoZXMgPC0gc2VwYXJhdGUoZGF0YSA9IGNyYXNoZXMsY29sID0gRGF0ZSwgaW50byA9IGMoIk1vbnRoIiwgIkRheSIsICJZZWFyIiksIHNlcCA9ICJcXC8iKQ0KYGBgDQoNCmBgYHtyfQ0KY3Jhc2hlcyA8LSBzZXBhcmF0ZShkYXRhID0gY3Jhc2hlcywgY29sID0gTG9jYXRpb24sIGludG8gPSBjKCJDaXR5IiwgIlJlZ2lvbiIsICJDb3VudHJ5IiksIHNlcCA9ICJcXCwgIikNCmBgYA0KDQotLS0NCg0KIyMgT3BlcmF0b3IgRGF0YSBBbmFseXNpcw0KVGhlIGJlbG93IGNvZGUgd2FzIHVzZWQgZm9yIHRoZSBgQ3Jhc2hlcyBQZXIgT3BlcmF0b3IgUGVyIFN0YXRlYCBncmFwaC4NCg0KYGBge3J9DQpzbWFsbF9ERiA8LSBjcmFzaGVzICU+JSANCiAgZ3JvdXBfYnkoT3BlcmF0b3IpICU+JSANCiAgY291bnQoT3BlcmF0b3IpICU+JSANCiAgYXJyYW5nZShkZXNjKG4pKSAlPiUgDQogIGZpbHRlcihuID4gNTApDQpgYGANCmBgYHtyfQ0Kb3BlcmF0b3JEYXRhIDwtIGNyYXNoZXMgJT4lDQogIGdyb3VwX2J5KE9wZXJhdG9yLCBZZWFyKSAlPiUgDQogIGNvdW50KE9wZXJhdG9yKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhuKSkgJT4lIA0KICBmaWx0ZXIobiA+IDApDQoNCm9wZXJhdG9yRGF0YQ0KYGBgDQpgYGB7cn0NCmRmIDwtIG9wZXJhdG9yRGF0YSAlPiUNCiAgZmlsdGVyKE9wZXJhdG9yICVpbiUgc21hbGxfREYkT3BlcmF0b3IpICU+JQ0KICBncm91cF9ieShZZWFyKQ0KDQpkZg0KYGBgDQoNCg0KIyMgQ3Jhc2ggQ291bnQgUGVyIFN0YXRlIERhdGEgQW5hbHlzaXMNClRoZSBiZWxvdyBjb2RlIHdhcyB1c2VkIGZvciB0aGUgYENyYXNoIENvdW50IFBlciBTdGF0ZWAgZ3JhcGguDQpgYGB7cn0NCm15X3NmIDwtIHN0X2FzX3NmKGZpbHRlcihjcmFzaGVzLCBMb25nPDAsIExhdD4wKSwgY29vcmRzID0gYygnTG9uZycsICdMYXQnKSkNCmBgYA0KYGBge3J9DQpzdGF0ZV9tYXBfZGF0YSA8LSBtYXAoJ3N0YXRlJywgZmlsbCA9IFRSVUUsIHBsb3QgPSBGQUxTRSkgJT4lIHN0X2FzX3NmKCkNCmBgYA0KYGBge3J9DQpteV9zZjwtc3Rfc2V0X2NycyhteV9zZiwgc3RfY3JzKHN0YXRlX21hcF9kYXRhKSkNCmBgYA0KYGBge3J9DQpzZjo6c2ZfdXNlX3MyKEZBTFNFKQ0KYGBgDQpgYGB7cn0NCnN0YXRlX21hcF9kYXRhJGNyYXNoX2NvdW50IDwtIGxlbmd0aHMoc3RfaW50ZXJzZWN0cyhzdGF0ZV9tYXBfZGF0YSxteV9zZikpDQpgYGANCg0KDQojIyBDcmFzaGVzIExvY2F0aW9uIERhdGEgQW5hbHlzaXMNClRoZSBiZWxvdyBjb2RlIHdhcyB1c2VkIGZvciB0aGUgYENyYXNoIExvY2F0aW9uYCBncmFwaC4NCmBgYHtyfQ0KZGZfZ2VvbSA8LSBjcmFzaGVzICU+JQ0KICBncm91cF9ieShZZWFyKSAlPiUgDQogIGZpbHRlcihSZWdpb24gJWluJSBjKCJBbGFiYW1hIiwgIkFyaXpvbmEiLCAiQXJrYW5zYXMiLCAiQ2FsaWZvcm5pYSIsICJDb2xhcmRvIiwgIkNvbm5lY3RpY3V0IiwgIkRlbGF3YXJlIiwgIkZsb3JpZGEiLCAiR2VvcmdpYSIsICJJZGFobyIsICJJbGxpbm9pcyIsICJJbmRpYW5hIiwgIklvd2EiLCAiS2Fuc2FzIiwgIktlbnR1Y3kiLCAiTG91c2lhbmEiLCAiTWFpbmUiLCAiTWFyeWxhbmQiLCAiTWFzc2FjaGV0dHVzZXR0cyIsICJNaWNoaWdhbiIsICJNaW5uZXNvdGEiLCAiTWlzc2lzc2lwcGkiLCAiTWlzc291cmkiLCAiTW9udGFuYSIsICJOZWJyYXNrYSIsICJOZXZhZGEiLCAiTmV3IEhhbXBzaGlyZSIsICJOZXcgSmVyc2V5IiwgIk5ldyBNZXhpY28iLCAiTmV3IFlvcmsiLCAiTm9ydGggQ2Fyb2xpbmEiLCAiTm9ydGggRGFrb3RhIiwgIk9oaW8iLCAiT2tsYWhvbWEiLCAiT3JlZ29uIiwgIlBlbm5zeWx2YW5pYSIsICJSaG9kZSBJc2xhbmQiLCAiU291dGggQ2Fyb2xpbmEiLCAiU291dGggRGFrb3RhIiwgIlRlbm5lc3NlZSIsICJUZXhhcyIsICJVdGFoIiwgIlZlcm1vbnQiLCAiVmlyZ2luaWEiLCAiV2FzaGluZ3RvbiIsICJXZXN0IFZpcmdpbmlhIiwgIldpc2NvbnNpbiIsICJXeW9taW5nIikpICU+JQ0KIHNlbGVjdChZZWFyLCBSZWdpb24sIExvbmcsIExhdCkNCiAgDQpgYGANCmBgYHtyfQ0KbXlfc2YyIDwtIHN0X2FzX3NmKGZpbHRlcihkZl9nZW9tLCBMb25nPDAsIExhdD4yNCksIGNvb3JkcyA9IGMoJ0xvbmcnLCAnTGF0JykpDQpgYGANCmBgYHtyfQ0Kc3RhdGVfbWFwX2RhdGEyIDwtIG1hcCgnc3RhdGUnLCBmaWxsID0gVFJVRSwgcGxvdCA9IEZBTFNFKSAlPiUgc3RfYXNfc2YoKQ0KYGBgDQpgYGB7cn0NCm15X3NmMiA8LSBzdF9zZXRfY3JzKG15X3NmMiwgc3RfY3JzKHN0YXRlX21hcF9kYXRhKSkNCmBgYA0KYGBge3J9DQpzZjo6c2ZfdXNlX3MyKEZBTFNFKQ0KYGBgDQpgYGB7cn0NCnN0YXRlX21hcF9kYXRhJGNyYXNoX2NvdW50IDwtIGxlbmd0aHMoc3RfaW50ZXJzZWN0cyhzdGF0ZV9tYXBfZGF0YSxteV9zZjIpKQ0KYGBgDQoNCg0KDQojIyBCaWdyYW0gRGF0YSBBbmFseXNpcw0KVGhlIGJlbG93IGNvZGUgd2FzIHVzZWQgZm9yIHRoZSBgQ3Jhc2ggU3VtbWFyeSBCaWdyYW1gIGdyYXBoLg0KYGBge3J9DQpiaWdyYW1EYXRhIDwtIGNyYXNoZXMgJT4lIA0KICBzZWxlY3QoU3VtbWFyeSkNCg0KYmlncmFtRGF0YQ0KYGBgDQpgYGB7cn0NCnN1bV9iaWdyYW0gPC0gYmlncmFtRGF0YSAlPiUgDQogIHVubmVzdF90b2tlbnMoYmlncmFtLCBTdW1tYXJ5LA0KICAgICAgICAgICAgICAgIHRva2VuID0gIm5ncmFtcyIsIG4gPSAyKQ0KYGBgDQpgYGB7cn0NCnN1bV9iaWdyYW0gJT4lIA0KICBjb3VudChiaWdyYW0sIHNvcnQgPSBUUlVFKQ0KYGBgDQpgYGB7cn0NCmJpZ3JhbXNfZmlsdGVyZWQgPC0gc3VtX2JpZ3JhbSAlPiUgDQogIHNlcGFyYXRlKGJpZ3JhbSwgaW50byA9IGMoIndvcmQxIiwgIndvcmQyIiksIHNlcCA9ICIgIikgJT4lIA0KICBmaWx0ZXIoIXdvcmQxICVpbiUgc3RvcF93b3JkcyR3b3JkKSAlPiUNCiAgZmlsdGVyKCF3b3JkMiAlaW4lIHN0b3Bfd29yZHMkd29yZCkNCmBgYA0KYGBge3J9DQpiaWdyYW1fY291bnQgPC0gYmlncmFtc19maWx0ZXJlZCAlPiUgDQogIGNvdW50KHdvcmQxLCB3b3JkMiwgc29ydCA9IFRSVUUpDQpiaWdyYW1fY291bnQNCmBgYA0KYGBge3J9DQpiaWdyYW1fdW5pdGUgPC0gYmlncmFtc19maWx0ZXJlZCAlPiUgDQogIHVuaXRlKGJpZ3JhbSwgd29yZDEsIHdvcmQyLCBzZXAgPSAiICIpDQpiaWdyYW1fdW5pdGUNCmBgYA0KYGBge3J9DQpiaWdyYW1fZ3JhcGggPC0gYmlncmFtX2NvdW50ICU+JSANCiAgZmlsdGVyKG4gPiA2MCkgJT4lIA0KICBncmFwaF9mcm9tX2RhdGFfZnJhbWUoKQ0KYGBgDQoNCg0KDQoNCg0KDQotLS0NCg0KIyBEYXRhIFZpc3VhbGl6YXRpb25zDQoNCg0KIyMgQ3Jhc2hlcyBwZXIgT3BlcmF0b3Igb3ZlciBUaW1lDQpgYGB7ciwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0NCmYgPC0gZ2dwbG90KGRhdGEgPSBkZiwgYWVzKHggPSBZZWFyLCB5ID0gbiwgY29sb3IgPSBPcGVyYXRvciwgZ3JvdXAgPSAxKSkgKw0KICBnZW9tX3BvaW50KHBhbGV0dGUgPSAiQmx1ZXMiKSsNCiAgZ2VvbV9saW5lKHBhbGV0dGUgPSAiQmx1ZXMiKSsNCiAgbGFicyh0aXRsZSA9ICJDcmFzaGVzIFBlciBPcGVyYXRvciBQZXIgWWVhciIsDQogICAgICAgeSA9ICIgIiwNCiAgICAgICB4ID0gIlllYXIiKSsNCiAgdGhlbWVfbWluaW1hbCgpKw0KICAjc2NhbGVfeF9jb250aW51b3VzKGV4cGFuZCA9ICkrDQogIHRoZW1lKHBsb3QudGl0bGUucG9zaXRpb24gPSAicGxvdCIpDQoNCmdncGxvdGx5KGYpDQpgYGANCg0KPiBUaGlzIGdyYXBoIHNob3dzIHRoZSB0b3AgNCBvcGVyYXRvcnMgdGhhdCBoYWQgdGhlIG1vc3QgY3Jhc2hlcy4gWW91IGNhbiBob3ZlciBvdmVyIHRoZSBwb2ludCB0byBzZWUgd2hpY2ggeWVhciBpdCBvY2N1cmVkIGluLCB0aGUgbnVtYmVyIG9mIGNyYXNocywgYW5kIHRoZSBvcGVyYXRvci4gT25lIG9mIHRoZSB0aGluZ3MgaSBmb3VuZCBpbnRyZXN0aW5nIGZyb20gdGhpcyBncmFwaCBpcyB0aGF0IERldXRzY2hlIEx1ZnRoYW5zYSBtYWRlIGl0IGludG8gdGhlIHRvcCA0IGZvciBtb3N0IGNyYXNoZXMsIGJ1dCB3YXMgb25seSBoYWQgY3Jhc2hlcyBmcm9tIDE5MDgtMTk0NS4gU29tZXRoaW5nIHRoYXQgbWF5IGJlIHdvcnRoIGxvb2tpbmcgYXQgaXMgYSBjcmFzaCByYXRpbyBvciBmbGlnaHRzIGZsb3duIHRvIGZsaWdodHMgY3Jhc2hlZC4NCg0KIyMgQ3Jhc2ggQ291bnQgYnkgU3RhdGUNCmBgYHtyIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTZ9DQprIDwtIGdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhID0gc3RhdGVfbWFwX2RhdGEsIGFlcyhmaWxsID0gY3Jhc2hfY291bnQpKSsNCiAgc2NhbGVfZmlsbF9kaXN0aWxsZXIocGFsZXR0ZT0iUmVkcyIsIGRpcmVjdGlvbiA9ICsxKSsNCiAgbGFicyh0aXRsZSA9ICJDcmFzaCBDb3VudCBQZXIgU3RhdGUiKSsNCiAgZ3VpZGVzKGZpbGwgPSBGQUxTRSkrDQogIHRoZW1lX21pbmltYWwoKSsNCiAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwbG90IikNCg0KZ2dwbG90bHkoaykNCmBgYA0KPiBJbiB0aGlzIGdyYXBoLCB3ZSBjYW4gc2VlIHRoZSBudW1iZXIgb2YgY3Jhc2hlcyB0aGF0IG9jY3VyZWQgaW4gZWFjaCBzdGF0ZS4gDQoNCiMjIENyYXNoIExvY2F0aW9uDQpgYGB7cn0NCnAgPC0gZ2dwbG90KCkgKw0KICBnZW9tX3NmKGRhdGEgPSBzdGF0ZV9tYXBfZGF0YSkrDQogIGdlb21fc2YoZGF0YSA9IG15X3NmMiwgY29sb3IgPSAncmVkJywgc2l6ZSA9IDAuMSkrDQogIHRoZW1lX21pbmltYWwoKSsNCiAgbGFicyh0aXRsZSA9ICJDcmFzaCBMb2NhdGlvbiBwZXIgU3RhdGUiKSsNCiAgdGhlbWUocGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwbG90IikNCg0KZ2dwbG90bHkocCkNCmBgYA0KPiBCdWlsZGluZyBvbiB0aGUgbGFzdCBncmFwaCwgdGhpcyBvbmUgc2hvd3MgdGhlIGxvY2F0aW9uIG9mIGVhY2ggY3Jhc2ggaW4gdGhlIHN0YXRlLiANCg0KIyMgQ3Jhc2ggU3VtbWFyeSBCaWdyYW0NCmBgYHtyIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD0xMH0NCnNldC5zZWVkKDIwMjEpDQphIDwtIGdyaWQ6OmFycm93KA0KICB0eXBlID0gImNsb3NlZCIsDQogIGxlbmd0aCA9IHVuaXQoLjEyLCAiaW5jaGVzIikNCikNCg0KZ2dyYXBoKGJpZ3JhbV9ncmFwaCwgbGF5b3V0ID0gImtrIikgKw0KICBnZW9tX2VkZ2VfbGluaygNCiAgICBhZXMoZWRnZV9hbHBoYSA9IG4pLA0KICAgIHNob3cubGVnZW5kID0gRkFMU0UsIGFycm93ID0gYSwNCiAgICBlZGdlX3dpZHRoID0gMSkgKw0KICBnZW9tX25vZGVfcG9pbnQoY29sb3IgPSAiYmxhY2siLA0KICAgICAgICAgICAgICAgICAgc2l6ZSA9IDQpICsNCiAgZ2VvbV9ub2RlX3RleHQoYWVzKGxhYmVsID0gbmFtZSksIHZqdXN0ID0gMSwgaGp1c3QgPSAxKSsNCiAgbGFicyh0aXRsZSA9ICJDcmFzaCBTdW1tYXJ5IEJpZ3JhbSIpKw0KICB0aGVtZV9taW5pbWFsKCkrDQogIHRoZW1lKHBsb3QudGl0bGUucG9zaXRpb24gPSAicGxvdCIpDQpgYGANCj4gSW4gdGhpcyBtb2RlbCwgd2UgY2FuIHNlZSB0aGUgbW9zdCBjb21tb24gd29yZCBwYXJpbmdzIGZyb20gdGhlIGNyYXNoIHN1bW1hcnkuIEkgdGhvdWdodCB0aGlzIHdvdWxkIGJlIGludHJlc3RpbmcgdG8gZXhwbG9yZSBhcyBpdCBjb3VsZCBnaXZlIHNvbWUgaW5zaWdodCBpbnRvIHdoYXQgY2F1c2VkIHRoZSBjcmFzaC4NCg0KDQotLS0NCg0KIyBDb25jbHVzaW9uDQoNClRoaXMgYW5hbHlzaXMgaGVscGVkIG1lIHNlZSBhIGRpZmZlcmVudCBzaWRlIG9mIHRoaXMgZGF0YS4gSXQgc2hvd2VkIG1lIHRoZSB3aGVyZSBhbmQgd2h5IHRoYXQgSSBtaXNzZWQgaW4gbXkgZmlyc3QgcHJvamVjdC4gSXQgd2FzIGludGVyZXN0aW5nIHRvIGV4cGxvcmUgdGhlIGRpZmZlcmVudCBzdGF0ZXMgY291bnRzLCBhbmQgdGhlIHRoZSBpbmRpdmlkdWFsIGxvY2F0aW9uIG9mIGVhY2ggY3Jhc2guIEl0IHdhcyBldmVuIGEgbGl0dGxlIHN1cnByaXNpbmcgdG8gZmluZCBvdXQgdGhhdCBDYWxpZm9ybmlhIGhhZCB0aGUgbW9zdCBjcmFzaGVzIG91dCBvZiB0aGUgY29udGluZW50YWwgVVMuIEFzIGZvciB0aGUgY3Jhc2ggZXhwbGFuYXRpb25zLCBzbyB3ZXJlIHRvIGJlIGV4cGVjdGVkLCBsaWtlIGVuZ2luZSAtPiBmYWlsdXJlIG9yIHdlYXRoZXIgLT4gY29uZGl0aW9ucywgYnV0IEkgdGhvdWdodCBpdCB3YXMgaW50ZXJlc3RpbmcgdG8gc2VlIHNvbWUgbGlrZSBjYXVnaHQgLT4gZmlyZSBhbmQgc3RydWNrIC0+IHRyZWUuDQoNCiMgRnV0dXJlIFdvcmtzDQoNCkkgYW0gcmVhbGx5IGRpc2FwcG9pbnRlZCB0aGF0IEkgd2FzIG5vdCBhYmxlIHRvIGdldCAnZ2dhbmltYXRlJyB0byB3b3JrLCBhbmQgSSBob3BlIHRvIGltcGxlbWVudCB0aGF0IGluIG15IGZ1dHVyZSBhbmFseXNpcy4gQWRkaXRpb25hbGx5LCBJIGhhZCBhICdsZWFmbGV0JyBwbG90IHRoYXQgd2FzIHJlYWxseSBtZXNzeSwgc28gSSBob3BlIHRvIHJlZmluZSB0aGF0IGFuZCBhZGQgdGhhdCB0byBhIGZ1dHVyZSB2ZXJzaW9uIG9mIHRoaXMgcHJvamVjdC4NCg0KDQpgYGB7cn0NCmRhdGVfZGYgPC0gc2VsZWN0KGNyYXNoZXMsIGMoTW9udGgsIFllYXIsIEZhdGFsaXRpZXMsIEFib2FyZCwgQUMuVHlwZSwgTG9uZywgTGF0KSkNCmBgYA0KDQpgYGB7cn0NCiNDaGFuZ2luZyB0aGUgZGF0YSB0eXBlIG9mIGZhdGFsaXRpZXMgdG8gYSBudW1lcmljDQpkYXRlX2RmJEZhdGFsaXRpZXMgPC0gYXMubnVtZXJpYyhkYXRlX2RmJEZhdGFsaXRpZXMpDQojQ2hhbmdpbmcgYWxsIHRoZSBOQXMgdG8gMHMNCmRhdGVfZGZbaXMubmEoZGF0ZV9kZildIDwtIDANCiNDaGFuZ2luZyB0aGUgZGF0YSB0eXBlIG9mIHllYXIgdG8gYSBudW1lcmljDQpkYXRlX2RmJFllYXIgPC0gYXMubnVtZXJpYyhkYXRlX2RmJFllYXIpDQpgYGANCg0KYGBge3J9DQojQ3JlYXRpbmcgYSBuZXcgY29sdW1uIGluIG91ciBkYXRhc2V0IGNhbGxlZCBkZWNhZGUNCmRhdGVfZGYgPC0gZGF0ZV9kZiAlPiUgDQogIG11dGF0ZShEZWNhZGUgPSBmbG9vcihZZWFyLzEwKSAqIDEwKQ0KYGBgDQoNCg0KYGBge3J9DQppbnRlcm5hdGlvbmFsX3NmIDwtIHN0X2FzX3NmKGRhdGVfZGYsIGNvb3JkcyA9IGMoJ0xvbmcnLCAnTGF0JykpDQpgYGANCmBgYHtyfQ0KaW50ZXJuYXRpb25hbF9zZiA8LSBzdF9zZXRfY3JzKGludGVybmF0aW9uYWxfc2YsIHN0X2NycyhzdGF0ZV9tYXBfZGF0YTMpKQ0KYGBgDQpgYGB7cn0NCnN0YXRlX21hcF9kYXRhMyA8LSBtYXBzOjptYXAoJ3N0YXRlJywgZmlsbCA9IFRSVUUsIHBsb3QgPSBGQUxTRSkgJT4lIA0KICBzdF9hc19zZigpDQpgYGANCg0KDQoNCg0KDQpgYGB7cn0NCmxpYnJhcnkobGVhZmxldCkNCmxlYWZsZXQoKSAlPiUgDQogIGFkZFRpbGVzKCkgJT4lIA0KICBhZGRDaXJjbGVNYXJrZXJzKGRhdGEgPSBpbnRlcm5hdGlvbmFsX3NmLCBmaWxsQ29sb3IgPSBpbnRlcm5hdGlvbmFsX3NmJFllYXIsIGZpbGxPcGFjaXR5ID0gMSwgc3Ryb2tlID0gRkFMU0UsIHJhZGl1cyA9IDUsIGdyb3VwID0gaW50ZXJuYXRpb25hbF9zZiRZZWFyKSAlPiUgDQogIGFkZExheWVyc0NvbnRyb2wob3ZlcmxheUdyb3VwcyA9IGludGVybmF0aW9uYWxfc2YkWWVhciwgb3B0aW9ucyA9IGxheWVyc0NvbnRyb2xPcHRpb25zKGNvbGxhcHNlZCA9IEZBTFNFKSkNCmBgYA==